package com.flyan.game.motafx.entity.terrain;

import cn.hutool.json.JSONUtil;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.entity.EntityFactory;
import com.almasb.fxgl.entity.SpawnData;
import com.almasb.fxgl.entity.Spawns;
import com.flyan.game.motafx.component.BackpackComponent;
import com.flyan.game.motafx.component.terrain.TerrainComponent;
import com.flyan.game.motafx.core.enums.EntityClassifyEnum;
import com.flyan.game.motafx.core.enums.EntityTypeEnum;
import com.flyan.game.motafx.core.panel.GameInfoPanel;
import com.flyan.game.motafx.core.util.console.ConsoleUtils;
import com.flyan.game.motafx.effect.terrain.StairEffect;

import static com.almasb.fxgl.dsl.FXGL.entityBuilder;

/**
 * 地形实体工厂
 *
 * @author flyan
 * @version 1.0
 * @email flyan_by_chenu@sina.com
 * @since 2025/1/31
 */
public class TerrainEntityFactory implements EntityFactory {

    /**
     * 空气墙
     */
    @Spawns("TERRAIN_AIR_WALL")
    public Entity airWall(SpawnData data) {
        data.put("info", JSONUtil.parseObj(new TerrainEntityInfo() {{
            setBlock(true);
            setCanDestroy(false);
        }}));
        return entityBuilder(data)
                .type(EntityTypeEnum.TERRAIN_AIR_WALL)
//                .view("materials/airwall.png") // 仅做测试打开，可看到空气墙
                .with(new TerrainComponent())
                .zIndex(EntityTypeEnum.TERRAIN_AIR_WALL.getZIndex().getIndex())
                .neverUpdated()
                .build();
    }

    /**
     * 地面
     */
    @Spawns("TERRAIN_GROUND")
    public Entity ground(SpawnData data) {
        data.put("info", JSONUtil.parseObj(new TerrainEntityInfo() {{
            setBlock(false);
            setCanDestroy(false);
        }}));
        return entityBuilder(data)
                .type(EntityTypeEnum.TERRAIN_GROUND)
                .with(new TerrainComponent())
                .zIndex(EntityTypeEnum.TERRAIN_GROUND.getZIndex().getIndex())
                .build();
    }

    /**
     * 墙
     */
    @Spawns("TERRAIN_WALL")
    public Entity wall(SpawnData data) {
        data.put("info", JSONUtil.parseObj(new TerrainEntityInfo() {{
            setBlock(true);
            setCanDestroy(true);
        }}));
        return entityBuilder(data)
                .type(EntityTypeEnum.TERRAIN_WALL)
                .with(new TerrainComponent())
                .zIndex(EntityTypeEnum.TERRAIN_WALL.getZIndex().getIndex())
                .build();
    }

    /**
     * 暗墙
     */
    @Spawns("TERRAIN_HIDDEN_WALL")
    public Entity hiddenWall(SpawnData data) {
        data.put("info", JSONUtil.parseObj(new TerrainEntityInfo() {{
            setBlock(true);
            setCanDestroy(true);
        }}));
        return entityBuilder(data)
                .type(EntityTypeEnum.TERRAIN_HIDDEN_WALL)
                .with(new TerrainComponent()
                        .setDestroyAnimateCode(11)
                        .setDestroySoundName("door.wav")
                        .setCollisionIsCanDestroyPredicate(o -> {
                            /* 角色触碰则打开暗墙 */
                            EntityTypeEnum oType = (EntityTypeEnum) o.getType();
                            if (oType.getClassify() == EntityClassifyEnum.CHARACTER) {
                                return true;
                            }
                            return false;
                        }))
                .zIndex(EntityTypeEnum.TERRAIN_HIDDEN_WALL.getZIndex().getIndex())
                .collidable()
                .build();
    }

    /**
     * 石墙
     */
    @Spawns("TERRAIN_STONE_WALL")
    public Entity stoneWall(SpawnData data) {
        data.put("info", JSONUtil.parseObj(new TerrainEntityInfo() {{
            setBlock(true);
            setCanDestroy(false);
        }}));
        return entityBuilder(data)
                .type(EntityTypeEnum.TERRAIN_STONE_WALL)
                .with(new TerrainComponent())
                .zIndex(EntityTypeEnum.TERRAIN_STONE_WALL.getZIndex().getIndex())
                .build();
    }

    /**
     * 下楼梯
     */
    @Spawns("TERRAIN_DOWN_STAIRS")
    public Entity downStairs(SpawnData data) {
        data.put("info", JSONUtil.parseObj(new TerrainEntityInfo() {{
            setBlock(false);
            setCanDestroy(false);
            addEffect(StairEffect.class.getName());
        }}));
        return entityBuilder(data)
                .type(EntityTypeEnum.TERRAIN_DOWN_STAIRS)
                .with(new TerrainComponent())
                .zIndex(EntityTypeEnum.TERRAIN_DOWN_STAIRS.getZIndex().getIndex())
                .collidable()
                .build();
    }

    /**
     * 上楼梯
     */
    @Spawns("TERRAIN_UP_STAIRS")
    public Entity upStairs(SpawnData data) {
        data.put("info", JSONUtil.parseObj(new TerrainEntityInfo() {{
            setBlock(false);
            setCanDestroy(false);
            addEffect(StairEffect.class.getName());
        }}));
        return entityBuilder(data)
                .type(EntityTypeEnum.TERRAIN_UP_STAIRS)
                .with(new TerrainComponent())
                .zIndex(EntityTypeEnum.TERRAIN_UP_STAIRS.getZIndex().getIndex())
                .collidable()
                .build();
    }

    /**
     * 黄门（普通门）
     */
    @Spawns("TERRAIN_DOOR")
    public Entity door(SpawnData data) {
        data.put("info", JSONUtil.parseObj(new TerrainEntityInfo() {{
            setBlock(true);
            setCanDestroy(true);
        }}));
        return entityBuilder(data)
                .type(EntityTypeEnum.TERRAIN_DOOR)
                .with(new TerrainComponent()
                        .setDestroyAnimateCode(4)
                        .setDestroySoundName("door.wav")
                        .setCollisionIsCanDestroyPredicate(o -> {
                            /* 角色触碰且有钥匙可打开 */
                            EntityTypeEnum oType = (EntityTypeEnum) o.getType();
                            if (oType.getClassify() == EntityClassifyEnum.CHARACTER) {
                                BackpackComponent backpackComponent = o.getComponent(BackpackComponent.class);
                                if (backpackComponent.getBackpack().hasItem(EntityTypeEnum.ITEM_KEY, 1)) {
                                    return true;
                                } else {
                                    ConsoleUtils.println("%s无法打开：没有%s".formatted("黄门", "黄钥匙"));
                                }
                            }
                            return false;
                        }).setCollisionDestroyConsumer(o -> {
                            /* 扣除角色钥匙 */
                            EntityTypeEnum oType = (EntityTypeEnum) o.getType();
                            if (oType.getClassify() == EntityClassifyEnum.CHARACTER) {
                                BackpackComponent backpackComponent = o.getComponent(BackpackComponent.class);
                                backpackComponent.getBackpack().removeItem(EntityTypeEnum.ITEM_KEY, 1);
                                GameInfoPanel.redraw();
                                ConsoleUtils.println("%s已打开：扣除%d把%s，还剩%d把"
                                        .formatted("黄门", 1, "黄钥匙",
                                                backpackComponent.getBackpack().itemAmount(EntityTypeEnum.ITEM_KEY)));
                            }
                        }))
                .zIndex(EntityTypeEnum.TERRAIN_DOOR.getZIndex().getIndex())
                .collidable()
                .build();
    }

    /**
     * 蓝门
     */
    @Spawns("TERRAIN_BLUE_DOOR")
    public Entity blueDoor(SpawnData data) {
        data.put("info", JSONUtil.parseObj(new TerrainEntityInfo() {{
            setBlock(true);
            setCanDestroy(true);
        }}));
        return entityBuilder(data)
                .type(EntityTypeEnum.TERRAIN_BLUE_DOOR)
                .with(new TerrainComponent()
                        .setDestroyAnimateCode(5)
                        .setDestroySoundName("door.wav")
                        .setCollisionIsCanDestroyPredicate(o -> {
                            /* 角色触碰且有钥匙可打开 */
                            EntityTypeEnum oType = (EntityTypeEnum) o.getType();
                            if (oType.getClassify() == EntityClassifyEnum.CHARACTER) {
                                BackpackComponent backpackComponent = o.getComponent(BackpackComponent.class);
                                if (backpackComponent.getBackpack().hasItem(EntityTypeEnum.ITEM_BLUE_KEY, 1)) {
                                    return true;
                                } else {
                                    ConsoleUtils.println("%s无法打开：没有%s".formatted("蓝门", "蓝钥匙"));
                                }
                            }
                            return false;
                        }).setCollisionDestroyConsumer(o -> {
                            /* 扣除角色钥匙 */
                            EntityTypeEnum oType = (EntityTypeEnum) o.getType();
                            if (oType.getClassify() == EntityClassifyEnum.CHARACTER) {
                                BackpackComponent backpackComponent = o.getComponent(BackpackComponent.class);
                                backpackComponent.getBackpack().removeItem(EntityTypeEnum.ITEM_BLUE_KEY, 1);
                                GameInfoPanel.redraw();
                                ConsoleUtils.println("%s已打开：扣除%d把%s，还剩%d把"
                                        .formatted("蓝门", 1, "蓝钥匙",
                                                backpackComponent.getBackpack().itemAmount(EntityTypeEnum.ITEM_KEY)));
                            }
                        }))
                .zIndex(EntityTypeEnum.TERRAIN_BLUE_DOOR.getZIndex().getIndex())
                .collidable()
                .build();
    }

    /**
     * 红门
     */
    @Spawns("TERRAIN_RED_DOOR")
    public Entity redDoor(SpawnData data) {
        data.put("info", JSONUtil.parseObj(new TerrainEntityInfo() {{
            setBlock(true);
            setCanDestroy(true);
        }}));
        return entityBuilder(data)
                .type(EntityTypeEnum.TERRAIN_RED_DOOR)
                .with(new TerrainComponent()
                        .setDestroyAnimateCode(6)
                        .setDestroySoundName("door.wav")
                        .setCollisionIsCanDestroyPredicate(o -> {
                            /* 角色触碰且有钥匙可打开 */
                            EntityTypeEnum oType = (EntityTypeEnum) o.getType();
                            if (oType.getClassify() == EntityClassifyEnum.CHARACTER) {
                                BackpackComponent backpackComponent = o.getComponent(BackpackComponent.class);
                                if (backpackComponent.getBackpack().hasItem(EntityTypeEnum.ITEM_BLUE_KEY, 1)) {
                                    return true;
                                } else {
                                    ConsoleUtils.println("%s无法打开：没有%s".formatted("红门", "红钥匙"));
                                }
                            }
                            return false;
                        }).setCollisionDestroyConsumer(o -> {
                            /* 扣除角色钥匙 */
                            EntityTypeEnum oType = (EntityTypeEnum) o.getType();
                            if (oType.getClassify() == EntityClassifyEnum.CHARACTER) {
                                BackpackComponent backpackComponent = o.getComponent(BackpackComponent.class);
                                backpackComponent.getBackpack().removeItem(EntityTypeEnum.ITEM_RED_KEY, 1);
                                GameInfoPanel.redraw();
                                ConsoleUtils.println("%s已打开：扣除%d把%s，还剩%d把"
                                        .formatted("红门", 1, "红钥匙",
                                                backpackComponent.getBackpack().itemAmount(EntityTypeEnum.ITEM_KEY)));
                            }
                        }))
                .zIndex(EntityTypeEnum.TERRAIN_RED_DOOR.getZIndex().getIndex())
                .collidable()
                .build();
    }

    /**
     * 绿门
     */
    @Spawns("TERRAIN_GREEN_DOOR")
    public Entity greenDoor(SpawnData data) {
        data.put("info", JSONUtil.parseObj(new TerrainEntityInfo() {{
            setBlock(true);
            setCanDestroy(true);
        }}));
        return entityBuilder(data)
                .type(EntityTypeEnum.TERRAIN_GREEN_DOOR)
                .with(new TerrainComponent()
                        .setDestroyAnimateCode(7)
                        .setDestroySoundName("door.wav")
                        .setCollisionIsCanDestroyPredicate(o -> {
                            /* 角色触碰且有钥匙可打开 */
                            EntityTypeEnum oType = (EntityTypeEnum) o.getType();
                            if (oType.getClassify() == EntityClassifyEnum.CHARACTER) {
                                BackpackComponent backpackComponent = o.getComponent(BackpackComponent.class);
                                if (backpackComponent.getBackpack().hasItem(EntityTypeEnum.ITEM_BLUE_KEY, 1)) {
                                    return true;
                                } else {
                                    ConsoleUtils.println("%s无法打开：没有%s".formatted("绿门", "绿钥匙"));
                                }
                            }
                            return false;
                        }))
                .zIndex(EntityTypeEnum.TERRAIN_GREEN_DOOR.getZIndex().getIndex())
                .collidable()
                .build();
    }

    /**
     * 机关门
     */
    @Spawns("TERRAIN_GATE_DOOR")
    public Entity gateDoor(SpawnData data) {
        data.put("info", JSONUtil.parseObj(new TerrainEntityInfo() {{
            setBlock(true);
            setCanDestroy(true);
        }}));
        return entityBuilder(data)
                .type(EntityTypeEnum.TERRAIN_GATE_DOOR)
                .with(new TerrainComponent()
                        .setDestroyAnimateCode(8)
                        .setDestroySoundName("door.wav")
                        .setCollisionIsCanDestroyPredicate(o -> {
                            /* 角色触碰则打开暗墙 */
                            EntityTypeEnum oType = (EntityTypeEnum) o.getType();
                            if (oType.getClassify() == EntityClassifyEnum.CHARACTER) {
                                return true;
                            }
                            return false;
                        }))
                .zIndex(EntityTypeEnum.TERRAIN_GATE_DOOR.getZIndex().getIndex())
                .collidable()
                .build();
    }

    /**
     * 牢门
     */
    @Spawns("TERRAIN_PRISON_DOOR")
    public Entity prisonDoor(SpawnData data) {
        data.put("info", JSONUtil.parseObj(new TerrainEntityInfo() {{
            setBlock(true);
            setCanDestroy(true);
        }}));
        return entityBuilder(data)
                .type(EntityTypeEnum.TERRAIN_PRISON_DOOR)
                .with(new TerrainComponent()
                        .setDestroyAnimateCode(9)
                        .setDestroySoundName("door.wav")
                        .setCollisionIsCanDestroyPredicate(o -> {
                            /* 角色触碰则打开暗墙 */
                            EntityTypeEnum oType = (EntityTypeEnum) o.getType();
                            if (oType.getClassify() == EntityClassifyEnum.CHARACTER) {
                                return true;
                            }
                            return false;
                        }))
                .zIndex(EntityTypeEnum.TERRAIN_PRISON_DOOR.getZIndex().getIndex())
                .collidable()
                .build();
    }

    @Spawns("TERRAIN_LEFT_ALTAR")
    public Entity TERRAIN_LEFT_ALTAR(SpawnData data) {
        data.put("info", JSONUtil.parseObj(new TerrainEntityInfo() {{
            setBlock(true);
            setCanDestroy(true);
        }}));
        return entityBuilder(data)
                .type(EntityTypeEnum.TERRAIN_LEFT_ALTAR)
                .with(new TerrainComponent())
                .zIndex(EntityTypeEnum.TERRAIN_LEFT_ALTAR.getZIndex().getIndex())
                .collidable()
                .build();
    }

    @Spawns("TERRAIN_RIGHT_ALTAR")
    public Entity TERRAIN_RIGHT_ALTAR(SpawnData data) {
        data.put("info", JSONUtil.parseObj(new TerrainEntityInfo() {{
            setBlock(true);
            setCanDestroy(false);
        }}));
        return entityBuilder(data)
                .type(EntityTypeEnum.TERRAIN_RIGHT_ALTAR)
                .with(new TerrainComponent())
                .zIndex(EntityTypeEnum.TERRAIN_RIGHT_ALTAR.getZIndex().getIndex())
                .collidable()
                .build();
    }

}
